/**
 * @file BaseFun.h
 * @author shikang999@126.com
 * @brief 
 * @version 0.1
 * @date 2025-06-20
 * 
 * @copyright Copyright (c) 2025
 * 
 */
#pragma once
#include "File.h"
#include "BaseData.h"

#include <map>
#include <functional>

namespace Solver
{
//1.函数类型
enum class FunType_E : uint16_t
{
    Nohting_E = 0,
    Hard5_1_E = 1,
    EasyAny_1_E = 2,

    NIST_Gauss3_E = 20,

    CEC2017_F1_E  = 101,
    CEC2017_F2_E  = 102,
    CEC2017_F3_E  = 103,
    CEC2017_F4_E  = 104,
    CEC2017_F5_E  = 105,
    CEC2017_F6_E  = 106,
    CEC2017_F7_E  = 107,
    CEC2017_F8_E  = 108,
    CEC2017_F9_E  = 109,
    CEC2017_F10_E = 110,
    CEC2017_F11_E = 111,
    CEC2017_F12_E = 112,
    CEC2017_F13_E = 113,
    CEC2017_F14_E = 114,
    CEC2017_F15_E = 115,
    CEC2017_F16_E = 116,
    CEC2017_F17_E = 117,
    CEC2017_F18_E = 118,
    CEC2017_F19_E = 119,
    CEC2017_F20_E = 120,
};
using vecFunType_t = std::vector<FunType_E>;

//2.问题难易程度
enum class DifficultyLevel_E : uint8_t
{
    Nothing_E = 0,
    Easy_E    = 1,//容易
    Medium_E  = 2,//中等
    Hard_E    = 3//困难
};

//3.基础函数类
class BaseFun
{
public:
    BaseFun(uint32_t dim, FunType_E type, DifficultyLevel_E diffLevel, uint32_t errorDim, const std::string &name, const std::string &description);
    virtual ~BaseFun();

    //设置ID
    void setID(uint32_t id);

    //获取ID
    uint32_t getID() const;

    //获取变量维度
    uint32_t getDim() const;

    //获取误差变量维度
    uint32_t getErrorDim() const;

    //获取函数类型
    FunType_E getType() const;

    //获取难易等级
    DifficultyLevel_E getLevel() const;

    //获取难易等级
    std::string getLevelStr() const;

    //获取函数名称
    const std::string &getName() const;

    //获取函数描述
    const std::string &getDescription() const;

    //获取及格线,如果某种算法优化的目标值不能小于此值,则可认为优化器性能不行
    value_t getPassY() const;

    //获取函数最优值
    value_t getBestY() const;

    //获取函数最优解
    virtual const VectorXd_t &getBestX();

    //获取函数求解下限
    const VectorXd_t &getMinX() const;

    //获取函数求解上限
    const VectorXd_t &getMax() const;

    //设置函数求解范围
    bool setXRange(value_t minX, value_t maxX);

    //设置函数求解范围
    bool setXRange(const VectorXd_t &minX, const VectorXd_t &maxX);

    //可重载归一化函数.比如需要变量取整,这时可以在这里面实现
    virtual void normVar(VectorXd_t &x);

    //实现最小化函数
    virtual value_t calcFun(const VectorXd_t &x) = 0;

    //在使用凸优化函数时,需要重载这个函数,计算误差,比如Dogleg算法
    virtual void calcErrorFun(const VectorXd_t &x, VectorXd_t &y);

    //在使用凸优化函数时,需要重载这个函数,计算一阶导雅克比函数,比如Dogleg算法
    virtual void calcJacobiDiff(const VectorXd_t &x, MatrixXd_t &jacobi);

    //存储信息到文件
    virtual void write(File &fw) const;

    //从文件读取信息
    virtual void read(File &fr);

protected:
    void writeBase(File &fw) const;

    void readBase(File &fr);

protected:
    uint32_t id_;            //函数ID
    FunType_E type_;         //函数类型
    DifficultyLevel_E level_;//难易等级
    uint32_t errorDim_;      //误差变量维度

    std::string name_;       //函数名称
    std::string description_;//一些函数描述

    value_t passY_;    //及格线,如果某种算法优化的目标值不能小于此值,则可认为优化器性能不行
    value_t bestY_;    //目标最优值
    VectorXd_t bestX_; //最优解
    VectorXd_t minX_;  //变量下限
    VectorXd_t maxX_;  //变量上限
};

using vecBaseFun_t = std::vector<std::shared_ptr<BaseFun>>;
using mapFun_t     = std::map<FunType_E, std::function<std::shared_ptr<BaseFun>(std::size_t)>>;

//5.
VectorXd_t initData(const vecValue_t &data);
}